import { EventActionSpec, EventActuatorInfo, EventObservationSpec, RemotePolicyInitializedEvent, TrainingBehaviorInitializedEvent, TrainingEnvironmentInitializedEvent } from "./Events";
// import { Macro } from "../../Macro";
import { ISensor } from "../Sensors/ISensor";
import { ActionSpec } from "../Actuators/ActionSpec";
import { IActuator } from "../Actuators/IActuator";
import { AnalyticsUtils } from "./AnalyticsUtils";



export class TrainingAnalytics {
    private static readonly _vendorKey: string = "unity.ml-agents";
    private static readonly _trainingEnvironmentInitializedEventName: string = "ml_agents_training_environment_initialized";
    private static readonly _trainingBehaviorInitializedEventName: string = "ml_agents_training_behavior_initialized";
    private static readonly _remotePolicyInitializedEventName: string = "ml_agents_remote_policy_initialized";

    private static readonly _sEventNames: string[] = [
        TrainingAnalytics._trainingEnvironmentInitializedEventName,
        TrainingAnalytics._trainingBehaviorInitializedEventName,
        TrainingAnalytics._remotePolicyInitializedEventName
    ];

    private static readonly _kMaxNumberOfElements: number = 1000;

    private static _sSentEnvironmentInitialized: boolean = false;

    // if(Macro.MLA_ANALYTICS_MODULE){
    private static _sEventsRegistered: boolean = false;
    private static _sSentRemotePolicyInitialized: Set<string> = new Set<string>();
    private static _sSentTrainingBehaviorInitialized: Set<string> = new Set<string>();
    // }


    private static _sTrainingSessionGuid: string = "";

    private static _sTrainerPackageVersion: string = "";
    private static _sTrainerCommunicationVersion: string = "";

    public static enableAnalytics(): boolean {
        // if (Macro.MLA_ANALYTICS_MODULE) {
        //     if (TrainingAnalytics._sEventsRegistered) {
        //         return true;
        //     }
        //     for (const eventName of TrainingAnalytics._sEventNames) {
        //        const result = Edit
        //     }
        //     TrainingAnalytics._sEventsRegistered = true;
        //     if (!TrainingAnalytics._sSentRemotePolicyInitialized) {
        //         TrainingAnalytics._sSentRemotePolicyInitialized = new Set<string>();
        //         TrainingAnalytics._sSentTrainingBehaviorInitialized = new Set<string>();
        //         TrainingAnalytics._sTrainingSessionGuid = Math.random().toString();
        //     }
        //     return TrainingAnalytics._sEventsRegistered;
        // }
        return false;
    }

    public static setTrainerInformation(packageVersion: string, communicationVersion: string): void {
        TrainingAnalytics._sTrainerPackageVersion = packageVersion;
        TrainingAnalytics._sTrainerCommunicationVersion = communicationVersion;
    }

    public static isAnalyticsEnabled(): boolean {
        // if (Macro.MLA_ANALYTICS_MODULE) {
        //     return EditorAnalytics.enabled;
        // }
        return false;

    }

    public static trainingEnvironmentInitialized(tbiEvent: TrainingEnvironmentInitializedEvent): void {
        if (!TrainingAnalytics.isAnalyticsEnabled()) {
            return;
        }
        if (!TrainingAnalytics.enableAnalytics()) {
            return;
        }
        if (TrainingAnalytics._sSentEnvironmentInitialized) {
            return;
        }

        TrainingAnalytics._sSentEnvironmentInitialized = true;
        tbiEvent.trainingSessionGuid = TrainingAnalytics._sTrainingSessionGuid;
        //  if (Macro.MLA_ANALYTICS_MODULE) {

        // }
    }

    public static remotePolicyInitialized(
        fullyQualifiedBehaviorName: string,
        sensors: ISensor[],
        actionSpec: ActionSpec,
        actuators: IActuator[]
    ): void {
        // if (Macro.MLA_ANALYTICS_MODULE) {
        //     if (!TrainingAnalytics.isAnalyticsEnabled()) {
        //         return;
        //     }
        //     if (!TrainingAnalytics.enableAnalytics()) {
        //         return;
        //     }
        //     const behaviorName: string = TrainingAnalytics.parseBehaviorName(fullyQualifiedBehaviorName);
        //     const added: boolean = TrainingAnalytics._sSentRemotePolicyInitialized.add(behaviorName);
        //     if (!added) {
        //         return;
        //     }


        // }
    }

    private static parseBehaviorName(fullyQualifiedBehaviorName: string): string {
        const lastQuestionIndex: number = fullyQualifiedBehaviorName.lastIndexOf("?");
        if (lastQuestionIndex < 0) {
            return fullyQualifiedBehaviorName;
        }

        return fullyQualifiedBehaviorName.substring(0, lastQuestionIndex);
    }

    private static sanitizeTrainingBehaviorInitializedEvent(tbiEvent: TrainingBehaviorInitializedEvent): TrainingBehaviorInitializedEvent {
        if (tbiEvent.config.length === 0 || tbiEvent.behaviorName.length !== 64) {
            tbiEvent.behaviorName = AnalyticsUtils.hash(TrainingAnalytics._vendorKey, tbiEvent.behaviorName);
        }

        return tbiEvent;
    }

    public static trainingBehaviorInitialized(rawTbiEvent: TrainingBehaviorInitializedEvent): void {
        // if (Macro.MLA_ANALYTICS_MODULE) {
        //     if (!TrainingAnalytics.isAnalyticsEnabled()) {
        //         return;
        //     }
        //     if (!TrainingAnalytics.enableAnalytics()) {
        //         return;
        //     }
        //     const tbiEvent: TrainingBehaviorInitializedEvent = TrainingAnalytics.sanitizeTrainingBehaviorInitializedEvent(rawTbiEvent);
        //     const behaviorName: string = tbiEvent.behaviorName;
        //     const added: boolean = TrainingAnalytics._sSentTrainingBehaviorInitialized.add(behaviorName);
        //     if (!added) {
        //         return;
        //     }

        //     tbiEvent.trainingSessionGuid = TrainingAnalytics._sTrainingSessionGuid;

        // }
    }

    private static getEventForRemotePolicy(
        behaviorName: string,
        sensors: ISensor[],
        actionSpec: ActionSpec,
        actuators: IActuator[]
    ): RemotePolicyInitializedEvent {
        const remotePolicyEvent: RemotePolicyInitializedEvent = new RemotePolicyInitializedEvent();
        remotePolicyEvent.behaviorName = AnalyticsUtils.hash(TrainingAnalytics._vendorKey, behaviorName);
        remotePolicyEvent.trainingSessionGuid = TrainingAnalytics._sTrainingSessionGuid;
        remotePolicyEvent.actionSpec = EventActionSpec.fromActionSpec(actionSpec);
        remotePolicyEvent.observationSpecs = new Array<EventObservationSpec>(sensors.length);
        for (const sensor of sensors) {
            remotePolicyEvent.observationSpecs.push(EventObservationSpec.fromSensor(sensor));
        }
        remotePolicyEvent.actuatorInfos = new Array<EventActuatorInfo>(actuators.length);
        for (const actuator of actuators) {
            remotePolicyEvent.actuatorInfos.push(EventActuatorInfo.fromActuator(actuator));
        }
        remotePolicyEvent.mlAgentsEnvsVersion = TrainingAnalytics._sTrainerPackageVersion;
        remotePolicyEvent.trainerCommunicationVersion = TrainingAnalytics._sTrainerCommunicationVersion;
        return remotePolicyEvent;
    }
}